package com.ruoyi.web.controller.system;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.business.domain.*;
import com.ruoyi.business.dto.BindPhoneNumberDTO;
import com.ruoyi.business.dto.LoginInfoDTO;
import com.ruoyi.business.service.*;
import com.ruoyi.business.domain.vo.FamilyMemberVO;
import com.ruoyi.business.service.impl.HikVisionServiceImpl;
import com.ruoyi.business.vo.*;
import com.ruoyi.business.vo.ResponseStatus;
import com.ruoyi.business.weapp.WeAppConfig;
import com.ruoyi.business.weapp.WeAppDataUtils;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysRegisterService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.*;

@RestController
@RequestMapping("/wx")
public class WxHttpApiController {

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    IWxUserService wxUserService;

    @Autowired
    SysRegisterService sysRegisterService;

    @Autowired
    SysLoginService sysLoginService;

    @Autowired
    ISysUserService ISysUserService;

    @Autowired
    IWxBannerConfigService wxBannerConfigService;

    @Autowired
    IWxNoticeService wxNoticeService;

    @Autowired
    IWxNewsService wxNewsService;

    @Autowired
    ISysConfigService sysConfigService;

    @Autowired
    IWxFeedbackService wxFeedbackService;

    @Autowired
    private IAuthBindingInfoService authBindingInfoService;

    @Autowired
    private IJobApplyService jobApplyService;

    @Autowired
    private IWxFaceDeviceService wxFaceDeviceService;

    @Autowired
    private IOperationRemindService operationRemindService;

    @Autowired
    private IMessageCenterService messageCenterService;

    @Autowired
    @Qualifier("HikVisionService")
    private HikVisionServiceImpl hikVisionService;

    @Autowired
    private RedisCache redisCache;

    public static final String INIT_PASSWORD = "admin123";

    /**
     * 状态启用
     */
    public static final String STATUS_ON = "1";

    /**
     * 状态关闭
     */
    public static final String STATUS_OFF = "0";

    /**
     * 小程序用户初始化角色
     */
    public static final Long[] WE_MINI_APP_ROLES = {3L};

    public static final String PHONE_NUMBER = "phoneNumber";


    private WxUser initWxUser(JSCode2SessionVO jsCode2SessionVO, LoginInfoDTO loginInfoDTO) {
        WxUser wxUser = new WxUser();
        wxUser.setAvatar(loginInfoDTO.getAvatar());
        wxUser.setNickName(loginInfoDTO.getNickName());
        wxUser.setUserName(loginInfoDTO.getNickName());
        wxUser.setCountry(loginInfoDTO.getCountry());
        wxUser.setProvince(loginInfoDTO.getProvince());
        wxUser.setCity(loginInfoDTO.getCity());
        wxUser.setLanguage(loginInfoDTO.getLanguage());
        wxUser.setOpenid(jsCode2SessionVO.getOpenid());
        wxUser.setSessionKey(jsCode2SessionVO.getSession_key());
        wxUser.setUnionid(jsCode2SessionVO.getUnionid());
        wxUser.setRecentLoginDate(DateUtils.getNowDate());
        return wxUser;
    }

    private RegisterBody initSysUser(WxUser wxUser) {
        RegisterBody registerBody = new RegisterBody();
        String userName = wxUser.getUserName();
        Random random = new Random();
        userName += String.valueOf(random.nextInt(1000));
        registerBody.setUsername(userName);
        registerBody.setPassword(INIT_PASSWORD);
        sysRegisterService.registerWithOutCaptcha(registerBody);
        return registerBody;
    }

    private Map<String, Object> initParamMap(String code) {
        HashMap<String, Object> params = new HashMap<>();
        params.put("APPID", WeAppConfig.APP_ID);
        params.put("SECRET", WeAppConfig.APP_SECRET);
        params.put("JSCODE", code);
        params.put("authorization_code", WeAppConfig.GRANT_TYPE);
        return params;
    }

    /**
     * 其实是小程序注册接口  小程序注册逻辑等同于第一次登录逻辑
     *
     * @param loginInfoDTO
     * @return
     */
    @PostMapping("/login")
    @Transactional
    public AjaxResult login(@RequestBody LoginInfoDTO loginInfoDTO) {
        System.out.println("登录开始---------------请求内容");
        System.out.println(JSONObject.toJSONString(loginInfoDTO));
        JSCode2SessionVO body;
        String token;
        Map<String, Object> resMap;

        try {
            ResponseEntity<JSCode2SessionVO> entity = restTemplate.getForEntity(WeAppConfig.JSCODE2SESSION_URL, JSCode2SessionVO.class, initParamMap(loginInfoDTO.getCode()));
            HttpStatus statusCode = entity.getStatusCode();
            if (statusCode != HttpStatus.OK) {
                throw new Exception();
            }
            body = entity.getBody();
            WxUser wxUser = initWxUser(body, loginInfoDTO);
            RegisterBody registerBody = initSysUser(wxUser);
            wxUser.setSysUserId(registerBody.getUserId());
            ISysUserService.insertUserAuth(registerBody.getUserId(), WE_MINI_APP_ROLES);
            int i = wxUserService.handleLogin(wxUser);

            if (i != 1) {
                throw new Exception();
            }
            token = sysLoginService.loginWithOutCaptcha(registerBody.getUsername(), INIT_PASSWORD);
            wxUser = wxUserService.selectWxUserByOpenId(body.getOpenid());
            if (wxUser == null) {
                return AjaxResult.error(20401, "该用户尚未注册");
            }
            resMap = new HashMap();
            resMap.put("token", token);
            resMap.put("wxUser", wxUser);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("登录异常----------------");
            System.out.println("----------------");
            System.out.println("----------------");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
        System.out.println("登录结果----------------");
        System.out.println(JSONObject.toJSONString(resMap));
        return AjaxResult.success("注册成功", resMap);
    }

    @GetMapping("/isRegister")
    @Transactional
    public AjaxResult isRegister(String code) {
        System.out.println("检测开始---------------请求内容");
        System.out.println(JSONObject.toJSONString(code));

        WxUser wxUser;
        JSCode2SessionVO body;
        Map<String, Object> resMap;
        try {
            ResponseEntity<JSCode2SessionVO> entity = restTemplate.getForEntity(WeAppConfig.JSCODE2SESSION_URL, JSCode2SessionVO.class, initParamMap(code));
            HttpStatus statusCode = entity.getStatusCode();
            if (statusCode != HttpStatus.OK) {
                throw new Exception();
            }
            body = entity.getBody();
            wxUser = wxUserService.selectWxUserByOpenId(body.getOpenid());
            if (wxUser != null) {
                wxUser.setSessionKey(body.getSession_key());
                wxUserService.updateWxUser(wxUser);
            }
            if (wxUser == null) {
                return AjaxResult.error(20401, "该用户尚未注册");
            }
            SysUser sysUser = ISysUserService.selectUserById(wxUser.getSysUserId());
            if (sysUser == null) {
                return AjaxResult.error(20401, "系统用户不存在");
            }
            String token = sysLoginService.loginWithOutCaptcha(sysUser.getUserName(), INIT_PASSWORD);
            resMap = new HashMap();
            resMap.put("token", token);
            resMap.put("wxUser", wxUser);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("检测注册异常----------------");
            System.out.println("----------------");
            System.out.println("----------------");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
        System.out.println("检测结果----------------");
        System.out.println(JSONObject.toJSONString(resMap));
        return AjaxResult.success(resMap);
    }

    @GetMapping("/getSystemInfo")
    @Transactional
    public AjaxResult getSystemInfo(Long villageId) {
        WxBannerConfig wxBannerConfig = new WxBannerConfig();
        wxBannerConfig.setStatus(STATUS_ON);
        List<WxBannerConfig> wxBannerConfigs = wxBannerConfigService.selectWxBannerConfigList(wxBannerConfig);
        if (wxBannerConfigs == null) {
            wxBannerConfigs = new ArrayList<>();
        }

        WxNotice wxNotice = new WxNotice();
        wxNotice.setStatus(STATUS_ON);


        WxNews wxNews = new WxNews();
        wxNews.setStatus(STATUS_ON);

        if (villageId != null && !StringUtils.isEmpty(villageId.toString())) {
            wxNews.setVillageId(villageId);
            wxNotice.setVillageId(villageId);
        }

        List<WxNews> wxNewsList = wxNewsService.selectWxNewsList(wxNews);
        List<WxNotice> wxNotices = wxNoticeService.selectWxNoticeList(wxNotice);

        if (wxNewsList == null) {
            wxNewsList = new ArrayList<>();
        }
        if (wxNotices == null) {
            wxNotices = new ArrayList<>();
        }

        String version = sysConfigService.selectConfigByKey("sys.info.version");
        String userAgreement = sysConfigService.selectConfigByKey("sys.info.userAgreement");
        String privacyPolicy = sysConfigService.selectConfigByKey("sys.info.user.privacyPolicy");

        Map<String, Object> resMap = new HashMap<>();
        resMap.put("wxBanners", wxBannerConfigs);
        resMap.put("wxNotices", wxNotices);
        resMap.put("wxNews", wxNewsList);
        resMap.put("version", version);
        resMap.put("userAgreement", userAgreement);
        resMap.put("privacyPolicy", privacyPolicy);
        return AjaxResult.success(resMap);
    }

    @PostMapping("/bindPhoneNumber")
    @Transactional
    public AjaxResult bindPhoneNumber(@RequestBody BindPhoneNumberDTO bindPhoneNumberDTO) {
        WxUser wxUser = wxUserService.selectWxUserByUserId(bindPhoneNumberDTO.getWxUserId());
        if (wxUser == null) {
            AjaxResult.error("绑定失败，用户不存在");
        }
        String sessionKey = wxUser.getSessionKey();
        JSONObject decrypt = null;
        try {
            WeAppDataUtils weAppDataUtils = new WeAppDataUtils(WeAppConfig.APP_ID, sessionKey);
            decrypt = weAppDataUtils.decrypt(bindPhoneNumberDTO.getEncryptedData(), bindPhoneNumberDTO.getIv());
            String phoneNumber = decrypt.get(PHONE_NUMBER).toString();
            wxUser.setPhone(phoneNumber);
            wxUserService.updateWxUser(wxUser);
        } catch (Exception e) {
            System.out.println(e);
            return AjaxResult.error("绑定手机号失败");
        }
        return AjaxResult.success(decrypt);
    }

    @PostMapping("/feedback")
    @Transactional
    public AjaxResult feedback(@RequestBody WxFeedback wxFeedback) {
        int i = wxFeedbackService.insertWxFeedback(wxFeedback);
        if (i != 1) {
            return AjaxResult.error("新增反馈");
        }
        return AjaxResult.success(wxFeedback);
    }

    @GetMapping("/getFamilyMembers")
    public AjaxResult getFamilyMembers(Long userId, Long villageId) {
        AuthBindingInfo authBindingInfo = authBindingInfoService.selectAuthBindingInfoByWxUserIdAndBindingVillageId(userId, villageId);
        if (authBindingInfo == null) {
            return AjaxResult.error("尚未绑定小区");
        }
        if (authBindingInfo.getHouseId() == null) {
            return AjaxResult.error("尚未绑定房屋号");
        }
        List<FamilyMemberVO> familyMembers = authBindingInfoService.getFamilyMembersByHouseId(authBindingInfo.getHouseId());
        if (familyMembers == null) {
            familyMembers = new ArrayList<>();
        }
        return AjaxResult.success(familyMembers);
    }

    @GetMapping("/checkHasApply")
    public AjaxResult checkHasApply(Long jobId, Long userId) {
        return AjaxResult.success(jobApplyService.selectJobApplyByJobIdAndUserId(jobId, userId));
    }

    // sn统一传递facedeviceid
    @GetMapping("/openGate/{sn}")
    public AjaxResult openGate(@PathVariable String sn) {

        WxFaceDevice wxFaceDevice = wxFaceDeviceService.selectWxFaceDeviceByFaceDeviceId(Long.valueOf(sn));
        if (wxFaceDevice == null) {
            return AjaxResult.error();
        }

        if (WxDeviceConstants.HIK_DEVICE.equals(wxFaceDevice.getDeviceType())) {
            try {
                SearchResult deviceList = hikVisionService.getDeviceList();
                List<MatchList> matchList = deviceList.getMatchList();
                int acGatewayIndex = 0;
                for (MatchList item : matchList) {
                    acGatewayIndex++;
                    if (wxFaceDevice.getHikDeviceIndex().equals(item.getDevice().getDevIndex())) {
                        break;
                    }
                }
                ResponseStatus open = hikVisionService.doorControl("open", String.valueOf(acGatewayIndex), wxFaceDevice.getHikDeviceIndex());
                if (open.getStatusCode() != 1) {
                    return AjaxResult.error();
                }
            } catch (Exception e) {
                return AjaxResult.error();
            }
            return AjaxResult.success();
        }

        sn = wxFaceDevice.getSn();
        List<HandleSettingInfo> cacheList = redisCache.getCacheList("SETTING_JOBS_" + sn);
        if (cacheList == null || cacheList.isEmpty()) {
            cacheList = new ArrayList<>();
        }
        HandleSettingInfo handleSettingInfo = new HandleSettingInfo();
        handleSettingInfo.setCmd("openGate");
        cacheList.add(handleSettingInfo);
        redisCache.setCacheList("SETTING_JOBS_" + sn, cacheList);
        redisCache.setCacheObject("OPEN_GATE_" + sn, false);
        for (int i = 0;i <= 6;i++) {
            try {
                Thread.sleep(1000); //设置暂停的时间 5 秒
                Boolean res = (Boolean)redisCache.getCacheObject("OPEN_GATE_" + sn);
                if (res) {
                    return AjaxResult.success();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                return AjaxResult.error();
            }
        }
        return AjaxResult.error();
    }

    @GetMapping("/checkOperationRemind/{wxUserId}/{villageId}")
    public AjaxResult checkOperationRemind(@PathVariable String wxUserId,@PathVariable String villageId) {
        HashMap<String, Object> res = new HashMap<>();

        OperationRemind operationRemind = new OperationRemind();
        operationRemind.setUserId(Long.valueOf(wxUserId));
        operationRemind.setIsComplete("0");
        operationRemind.setOperationType(OperationRemindType.JOB);
        res.put(OperationRemindType.JOB, operationRemindService.selectOperationRemindList(operationRemind));

        operationRemind.setOperationType(OperationRemindType.RENT_HOUSE);
        res.put(OperationRemindType.RENT_HOUSE, operationRemindService.selectOperationRemindList(operationRemind));

        operationRemind.setOperationType(OperationRemindType.REFLASH_LOGIN_INFO);
        res.put(OperationRemindType.REFLASH_LOGIN_INFO, operationRemindService.selectOperationRemindList(operationRemind));

        operationRemind.setOperationType(OperationRemindType.NOTICE);
        operationRemind.setVillageId(Long.valueOf(villageId));
        res.put(OperationRemindType.NOTICE, operationRemindService.selectOperationRemindList(operationRemind));

        MessageCenter messageCenter = new MessageCenter();
        messageCenter.setDestUserId(wxUserId);
        messageCenter.setIsRead("0");
        res.put(OperationRemindType.MESSAGE_LEFT, messageCenterService.selectMessageCenterList(messageCenter));

        return AjaxResult.success(res);

    }
}